//
//  XMLDocument.swift
//  C150805_libxml2
//
//  Created by yao_yu on 15/8/5.
//  Copyright © 2015年 yao_yu. All rights reserved.
//

import Foundation


class XMLDocument {
    private var isXML = true
    var data:NSData?
    var encoding = NSUTF8StringEncoding
    
    typealias htmlDocPtr = xmlDocPtr
    var xmlDoc:xmlDocPtr = nil
    var htmlDoc:htmlDocPtr {
        get {return xmlDoc }
        set {xmlDoc = newValue}
    }
    
    init?(data _data:NSData?, encoding:NSStringEncoding, isXML:Bool) {
        if let data = _data where data.length > 0 {
            self.isXML = isXML
            self.data = data
            self.encoding = encoding
            
            let cBuffer = UnsafePointer<CChar>(data.bytes)
            let cSize = CInt(data.length)
            let cfEncoding = CFStringConvertNSStringEncodingToEncoding(encoding)
            let cfEncodingAsString:CFStringRef = CFStringConvertEncodingToIANACharSetName(cfEncoding)
            print(cfEncodingAsString)
            let cEncoding:UnsafePointer<CChar> = CFStringGetCStringPtr(cfEncodingAsString, 0)
            
            if isXML {
                let options = CInt(XML_PARSE_RECOVER.rawValue)
                xmlDoc = xmlReadMemory(cBuffer, cSize, nil, cEncoding, options)
            } else {
                let options = CInt(HTML_PARSE_RECOVER.rawValue | HTML_PARSE_NOWARNING.rawValue | HTML_PARSE_NOERROR.rawValue)
                htmlDoc = htmlReadMemory(cBuffer, cSize, nil, cEncoding, options)
            }
            if xmlDoc == nil {
                return nil
            } else {
//                var node = xmlDocGetRootElement(xmlDoc)
//                print(("根节点名称:", node.name))
            }
        } else {
            return nil
        }
    }
    
    convenience init?(data: NSData?, isXML: Bool) {
        self.init(data: data, encoding: NSUTF8StringEncoding, isXML: isXML)
    }

    convenience init?(xmlData: NSData, encoding: NSStringEncoding) {
        self.init(data: xmlData, encoding: encoding, isXML: true)
    }
    
    convenience init?(xmlData: NSData) {
        self.init(data: xmlData, isXML: true)
    }
    
    convenience init?(htmlData: NSData, encoding: NSStringEncoding) {
        self.init(data: htmlData, encoding: encoding, isXML: false)
    }
    
    convenience init?(htmlData: NSData) {
        self.init(data: htmlData, isXML: false)
    }
    
    convenience init?(contentsOfURL url: NSURL, encoding: NSStringEncoding, isXML: Bool) {
        let data = NSData(contentsOfURL: url)
        self.init(data: data, encoding: encoding, isXML: isXML)
    }
    
    convenience init?(contentsOfURL url: NSURL, isXML: Bool) {
        self.init(contentsOfURL: url, encoding: NSUTF8StringEncoding, isXML: isXML)
    }
    
    convenience init?(xmlURL: NSURL) {
        self.init(contentsOfURL: xmlURL, isXML: true)
    }
    
    convenience init?(htmlURL: NSURL) {
        self.init(contentsOfURL: htmlURL, isXML: false)
    }
    
    convenience init?(xmlString: String, encoding: NSStringEncoding) {
        let data = xmlString.dataUsingEncoding(encoding, allowLossyConversion: false)
        self.init(data: data, encoding: encoding, isXML: true)
    }
    
    convenience init?(htmlString: String, encoding: NSStringEncoding) {
        let data = htmlString.dataUsingEncoding(encoding, allowLossyConversion: false)
        self.init(data: data, encoding: encoding, isXML: false)
    }

    convenience init?(xmlString: String) {
        let data = xmlString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
        self.init(data: data, isXML: true)
    }
    
    convenience init?(htmlString: String) {
        let data = htmlString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
        self.init(data: data, isXML: false)
    }
    
    deinit {
        xmlFreeDoc(xmlDoc)
    }
    

    lazy var rootNode: XMLNode? = {
        let rootNodePointer = xmlDocGetRootElement(self.xmlDoc)
        if rootNodePointer == nil {
            return nil
        } else {
            return XMLNode(xmlNode: rootNodePointer, xmlDocument: self)
        }
        }()
    
    func xPath(xPath: String) -> [XMLNode]? {
        return self.rootNode?.xPath(xPath)
    }
}

// MARK: - Equatable
extension XMLDocument: Equatable { }
func ==(lhs: XMLDocument, rhs: XMLDocument) -> Bool {
    return lhs.xmlDoc == rhs.xmlDoc
}